<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="count"></div>
    <script>
      // hooks
      // 在react中 react使用链表存储多个hooks
      // react 参用的是 “不带头单向非循环结构”
      // 结构如下
      // [memorizedState] -> [data][next] -> [data][next] -> null
      const fiber = {
        type: FunctionComponent,
        memorizdState: null,
        alternate: null,
      };

      // hook 的中间变量，可以理解为正在工作的 hook 或尾 hook
      // 第一次是null
      let workInProgressHook = null;
      // 创建hook 得函数
      const updateWorkInProgressHook = () => {
        // 第一次执行的时候 和 状态更新的时候 执行的逻辑是不一样
        // 第一次执行 会把 hook 挂在到fiber.memorizdState
        // 当状态更新的时候 不需要再挂载 那么如何区分是第一次还是更新？
        // 在 React 当中当渲染组件之后会把当前的 Fiber 节点信息设置到 Fiber 的 alternate 属性上
        // 所以我们可以通过判断当前 Fiber 节点是否存在 alternate 来判断当前是属于更新阶段还是初始化阶段
        // 如果是初始化阶段，那么我们就去 Fiber 的 alternate 属性上获取相应的 hook。

        // 获取已经挂载过的hooks
        const current = fiber.alternate;

        if (current) {
          // 更新逻辑 获取旧的hook
          fiber.memorizdState = current.memorizdState;
          if (workInProgressHook) {
            // 不是头节点
            hook = workInProgressHook = workInProgressHook.next;
          } else {
            // 是头节点
            hook = workInProgressHook = current.memorizdState;
          }
        } else {
          // 如果有挂在过的 就更新
          hook = {
            memorizedState: null, // 存储 hook
            next: null, // next 指针，指向下一个 hook}
          };

          if (workInProgressHook) {
            // 如果 workInProgressHook 不是 null
            workInProgressHook = workInProgressHook.next = hook;
          } else {
            // 如果 workInProgressHook 是 null, 表示是头节点
            workInProgressHook = fiber.memorizdState = hook;
          }
        }

        return hook;
      };

      function useReducer(reducer, initalState) {
        if (!fiber.memorizdState) fiber.memorizdState = initalState;
        // 为什么使用 bind 请看 javascript and leetCode 文件夹下面的 手撕bind
        // 为什么要是有闭包  因为当我们多次调用 useReducer时候
        // useReducer(x => x+1 )
        // useReducer(x => x+2 )
        // useReducer(x => x+3 )
        // 当我们使用 useReducer返回的 setXX 时, 他永远只会进行+3 因为使全局fiber
        // 闭包能让他们进行独立的一个状态 不会被污染
        console.log("fiber ===> ", fiber);
        const dispatch = dispatchAction.bind(null, fiber, reducer);
        return [fiber.memorizdState, dispatch];
      }

      // 参数 action 就是 dispatch 函数执行的时候传递进来的参数
      const dispatchAction = (fiber, reducer, action) => {
        // 执行 reducer
        fiber.memorizdState = reducer ? reducer(action) : action;
        // 更新以后 重新执行函数 更新数据
        fiber.type();
      };

      const useState = (initalState) => {
        return useReducer(null, initalState);
      };

      function FunctionComponent() {
        // const [count, setCount] = useReducer((x) => x + 1, 0);
        const [state, setstate] = useState(18);
        console.log("state, setstate ==>  ", state, setstate);

        document.getElementById("count").innerHTML = state;
        return {
          state,
          setstate,
        };
      }

      const { state, setstate } = fiber.type();
      window.$setState = setstate;
    </script>
  </body>
</html>
